//
//  Router.swift
//  DYSwiftRouter
//
//  Created by 黄德玉 on 2018/9/6.
//  Copyright © 2018年 none. All rights reserved.
//
//foo://username:password@example.com:8042/over/there/index.dtb?type=animal&name=narwhal#nose
//\_/ \________________/ \_________/ \__/\____________________/\____________________/ \__/
//    |           |              |        |            |                      |            |
//scheme   userinfo          host     port         path                  query       fragment

import UIKit

// 获取工程名字的方法
private func nameForProgram()->String{
    var programName = ""
    if programName.isEmpty {
        programName = Bundle.main.infoDictionary!["CFBundleExecutable"]! as! String
    }
    return programName
}



public class BaseRouterNode {
//    public var path:String   // URL路径,对于iOS开发，由于严格的层级关系，无法为页面指定路径，只能根据当前页面展开的形式，得到当前页面的路径。
    public var component:String                     // 组件名称
    public var name:String                          // 路由节点名称
    
    public var redirect:[String:String]?            // 重定向:{"name":A,"component":B}，不常用
    public var alias:[String]?                      // 别名，一个组件可以有多个别名， 不常用
    public var meta:Any?                            // 路由元信息， 例如是否需要登录等信息。
    public var propKeys:[String]?                   // 模式匹配，TODO: 组件启动方式多样化，定死的模式匹配行不行？
    init(component:String,name:String) {
        self.name = name
        self.component = component
    }
}

public class RouterNode : BaseRouterNode  {
    public var props:Any?                               // 组件传参，TODO： 为组件定义模式匹配，可以规范化组件。
    public var onBackAction:((Any?)->Void)?             // 组件事件回传，用于组件通信
    
    public var fragment:Int?                            // 表示相同链路下的页面数量,上层封装为只读
    public var path:String?                             // 路由节点的路径， 作为只读
    public weak var currentComponent:UIViewController?  // 当前节点对应的组件, 这个代价是不是太高了，每个组件节点必须维护一个weak的属性？
    
//    public func push(name:String){
//
//    }
}

public class Router{
    
    private static var routerMap:[String:Any] = [:]
    
    // 注册所有的节点
    public class func register(nodes:[BaseRouterNode]){
        nodes.forEach { (node) in
            #if DEBUG
            // 在开发阶段，需要检测组件对应的ViewController是否存在。
            // 这是一个坑，需要加上项目名称
            let aClass = NSClassFromString(nameForProgram() + "." + node.component) as? UIViewController.Type;
            if  aClass == nil {
                debugPrint("注册类名失败,当前类不存在\(node.component)");
                return
            }
            #endif
            // 是否有重定向的信息,重定向的优先级最高
            if let redirect = node.redirect{
                let name = redirect.keys.first
                let component = redirect.values.first
                if (name == nil || component == nil){
                    return
                }
                #if DEBUG       // 在开发阶段需要将检查name重名的功能给打开。
                if routerMap.keys.contains(name!) {
                    print("############\(node.component):重定向的路由节点 \(name!) 已存在.#############")
                    return
                }
                #endif
                routerMap[name!] = node
                return
            }
            
            // 别名信息，和name兼容
            if let alias = node.alias{
                #if DEBUG       // 在开发阶段需要将检查name重名的功能给打开。
                for item in alias{
                    if routerMap.keys.contains(item) {
                        print("############\(node.component):别名的路由节点 \(item) 已存在.#############")
                        return
                    }
                }
                #endif
            }
            
            
            
            
            let name = node.name
            if !routerMap.keys.contains(name) {
                routerMap[name] = node;
            }else{
                debugPrint("相同名字的节点已经存在（\(name)）")
            }
        }
    }
    
    
}


